home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / Examples ƒ / Example / IC Resource ƒ / Syslog Component ƒ / Libsprintf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-15  |  13.2 KB  |  690 lines  |  [TEXT/SPM ]

  1. /*
  2.     libsprintf.c
  3.     
  4.     Stand alone sprintf clone (stand alone meaning that one doesn't need to use the ansi libraries to use this).
  5.     
  6.     Most of this is © Symantec, Inc. (I just had to do a little tinkering to get it to be stand alone...)
  7.     
  8.     06/26/95 - Updated for PPC.
  9. */
  10.  
  11. #include "libsprintf.h"
  12.  
  13. #ifdef _USE_ANSI_ // then use the ansi libraries...
  14.  
  15. #include <stdio.h>
  16. #include <strings.h>
  17.  
  18. #define libsprintf sprintf
  19.  
  20. #else // use our library...
  21.  
  22. // set the following to false to include floating point conversions
  23. #if 1
  24. #define _NOFLOATING_
  25. #endif
  26.  
  27. #include <stdarg.h>
  28.  
  29. #define BUFLEN            512
  30. #define TRUE            1
  31. #define FALSE            0
  32.  
  33. // set the following to 1 to specify register settings, otherwise the
  34. // compiler will try to optimize register settings.
  35. #if 0
  36. #define REGISTER register
  37. #else
  38. #define REGISTER
  39. #endif
  40.  
  41. long s_errno;
  42.  
  43. static struct format {
  44.     unsigned         leftJustify : 1;
  45.     unsigned         forceSign : 1;
  46.     unsigned         altForm : 1;
  47.     unsigned         zeroPad : 1;
  48.     unsigned         havePrecision : 1;
  49.     unsigned         hSize : 1;
  50.     unsigned         lSize : 1;
  51.     unsigned         LSize : 1;
  52.     char            sign;
  53.     char            exponent;
  54.     int                fieldWidth;
  55.     int                precision;
  56. } default_format;
  57.  
  58. #ifndef _NOFLOATING_
  59.  
  60. #include <fp.h>
  61.  
  62. struct LibDecRec {
  63.     decimal    dec;
  64.     /* following fields aren't used by SANE */
  65.     short            min;
  66.     short            dot;
  67.     short            max;
  68. };
  69.  
  70. typedef struct LibDecRec LibDecRec;
  71.  
  72. void libf2d(int, int, struct LibDecRec *, long double);
  73. static void post_conversion(LibDecRec *d);
  74.  
  75. #endif
  76.  
  77. char libstrlen(char* cstr){
  78.     REGISTER char len=0;
  79.     REGISTER char* str=cstr;
  80.     
  81.     if (*str!=0){
  82.         do {
  83.             len++;
  84.             str++;
  85.         } while (*str!=0);
  86.     }
  87.     
  88.     return len;
  89. }
  90.  
  91. void libfixnl(char* buf){
  92.     REGISTER char* cp=buf;
  93.     
  94.     if ((cp==(char*)0)||(*cp==0))
  95.         return;
  96.     
  97.     do {
  98.         if (*cp=='\n')
  99.             *cp=0x06;
  100.         cp++;
  101.     } while (*cp!=0);
  102. }
  103.  
  104. int libsprintf(char *s, const char *fmt, ...){
  105.     return libvsprintf(s, fmt, __va(fmt));
  106. }
  107.  
  108. int libvsprintf(char *cfp,const char *fmt,va_list arg){
  109.     REGISTER int c, i, j, nwritten = 0;
  110.     REGISTER unsigned long n;
  111.     long double x;
  112.     REGISTER char *s;
  113.     REGISTER char* fp=cfp;
  114.     char buf[BUFLEN], *digits, *t;
  115.     char* endbuf;
  116.     struct format F;
  117. #ifndef _NOFLOATING_
  118.     LibDecRec D;
  119. #endif
  120.     
  121.     // buffers containing strings full of zeros and spaces
  122.     char* __gZeroString;
  123.     char* __gSpaceString;
  124.  
  125.     // variables used by libvsprintf
  126.     char __gFloatConst[]="\6>>>>>>";
  127.     char __gCapDigits[]= "0123456789ABCDEF";
  128.     char __gLowDigits[]= "0123456789abcdef";
  129.  
  130.     __gZeroString=(char*)NewPtr(BUFLEN);
  131.     __gSpaceString=(char*)NewPtr(BUFLEN);
  132.     
  133.     for (i=0;i<BUFLEN;i++){
  134.         __gZeroString[i]='0';
  135.         __gSpaceString[i]=' ';
  136.     }
  137.     
  138.     // init default_format
  139.     // this may/may not be necessary (I don't know what some
  140.     // optimizers might be doing; this will ensure correct entries
  141.     
  142.     default_format.leftJustify=FALSE;
  143.     default_format.forceSign=FALSE;
  144.     default_format.altForm=FALSE;
  145.     default_format.zeroPad=FALSE;
  146.     default_format.havePrecision=FALSE;
  147.     default_format.hSize=FALSE;
  148.     default_format.lSize=FALSE;
  149.     default_format.LSize=FALSE;
  150.     default_format.sign=0;
  151.     default_format.exponent=0;
  152.     default_format.fieldWidth=0;
  153.     default_format.precision=0;
  154.     
  155.     s_errno=(long)paramErr;
  156.     
  157.     // only calculate endbuf once
  158.     endbuf=&(buf[BUFLEN]);
  159.     
  160.     for (c = *fmt; c; c = *++fmt) {
  161.         // reset the format
  162.         F = default_format;
  163.         
  164.         if (c != '%'){
  165. #if 1
  166.             s=(char*)fmt;
  167.             
  168.             for (i=0;1;i++){
  169.                 if ((fmt[i]=='%')||(fmt[i]==0)){
  170.                     // i points at a terminator
  171.                     // allow the rest of the function to copy the string n stuff
  172.                     fmt+=(i-1);
  173.                     goto EndOfSwitch;
  174.                 }
  175.             }
  176. #else
  177.             goto copy1;
  178. #endif
  179.         }
  180.         
  181.             /*  decode flags  */
  182.             
  183.         for (;;) {
  184.             c = *++fmt;
  185.             if (c == '-')
  186.                 F.leftJustify = TRUE;
  187.             else if (c == '+')
  188.                 F.forceSign = TRUE;
  189.             else if (c == ' ')
  190.                 F.sign = ' ';
  191.             else if (c == '#')
  192.                 F.altForm = TRUE;
  193.             else if (c == '0')
  194.                 F.zeroPad = TRUE;
  195.             else
  196.                 break;
  197.         }
  198.         
  199.             /*  decode field width  */
  200.             
  201.         if (c == '*') {
  202.             if ((F.fieldWidth = va_arg(arg, int)) < 0) {
  203.                 F.leftJustify = TRUE;
  204.                 F.fieldWidth = -F.fieldWidth;
  205.             }
  206.             c = *++fmt;
  207.         } else {
  208.             for (; c >= '0' && c <= '9'; c = *++fmt)
  209.                 F.fieldWidth = (10 * F.fieldWidth) + (c - '0');
  210.         }
  211.         
  212.             /*  decode precision  */
  213.             
  214.         if (c == '.') {
  215.             if ((c = *++fmt) == '*') {
  216.                 F.precision = va_arg(arg, int);
  217.                 c = *++fmt;
  218.             } else {
  219.                 for (; c >= '0' && c <= '9'; c = *++fmt)
  220.                     F.precision = (10 * F.precision) + (c - '0');
  221.             }
  222.             if (F.precision >= 0)
  223.                 F.havePrecision = TRUE;
  224.         }
  225.         
  226.             /* decode size modifiers */
  227.             
  228.         while ((c=='h')||(c=='l')||(c=='L')){
  229.             if (c=='h')
  230.                 F.hSize=TRUE;
  231.             else if (c=='l')
  232.                 F.lSize=TRUE;
  233.             else
  234.                 F.LSize=TRUE;
  235.             
  236.             c=*++fmt;
  237.         }
  238.         
  239.             /*  perform appropriate conversion  */
  240.         
  241.         s =endbuf;
  242.         if (F.leftJustify)
  243.             F.zeroPad = FALSE;
  244.         
  245. conv:    switch (c) {
  246.                 
  247.                 /*  decimal (signed)  */
  248.                 
  249.             case 'd':
  250.             case 'i':
  251.                 if (F.lSize)
  252.                     n = va_arg(arg, long);
  253.                 else
  254.                     n = va_arg(arg, int);
  255.                 if (F.hSize)
  256.                     n = (short) n;
  257.                 if ((long) n < 0) {
  258.                     n = -n;
  259.                     F.sign = '-';
  260.                 } else if (F.forceSign)
  261.                     F.sign = '+';
  262.                 goto decimal;
  263.                 
  264.                 /*  decimal (unsigned)  */
  265.                 
  266.             case 'u':
  267.                 if (F.lSize)
  268.                     n = va_arg(arg, unsigned long);
  269.                 else
  270.                     n = va_arg(arg, unsigned int);
  271.                 if (F.hSize)
  272.                     n = (unsigned short) n;
  273.                 F.sign = 0;
  274.                 goto decimal;
  275.                 
  276.                 /*  decimal (common code)  */
  277.  
  278. decimal:
  279.                 if (!F.havePrecision) {
  280.                     if (F.zeroPad) {
  281.                         F.precision = F.fieldWidth;
  282.                         if (F.sign)
  283.                             --F.precision;
  284.                     }
  285.                     if (F.precision < 1)
  286.                         F.precision = 1;
  287.                 }
  288.                 for (i = 0; n; n /= 10, i++)
  289.                     *--s = n % 10 + '0';
  290.                 if (i<F.precision){
  291.                     j=(F.precision-i);
  292.                     s-=j;
  293.                     BlockMoveData((Ptr)__gZeroString,(Ptr)s,j);
  294.                     i=F.precision;
  295.                 }
  296.                 if (F.sign) {
  297.                     *--s = F.sign;
  298.                     i++;
  299.                 }
  300.                 break;
  301.                 
  302.                 /*  octal (unsigned)  */
  303.                 
  304.             case 'o':
  305.                 if (F.lSize)
  306.                     n = va_arg(arg, unsigned long);
  307.                 else
  308.                     n = va_arg(arg, unsigned int);
  309.                 if (F.hSize)
  310.                     n = (unsigned short) n;
  311.                 if (!F.havePrecision) {
  312.                     if (F.zeroPad)
  313.                         F.precision = F.fieldWidth;
  314.                     if (F.precision < 1)
  315.                         F.precision = 1;
  316.                 }
  317.                 for (i = 0; n; n /= 8, i++)
  318.                     *--s = n % 8 + '0';
  319.                 if (F.altForm && i && *s != '0') {
  320.                     *--s = '0';
  321.                     i++;
  322.                 }
  323.                 if (i<F.precision){
  324.                     j=(F.precision-i);
  325.                     s-=j;
  326.                     BlockMoveData((Ptr)__gZeroString,(Ptr)s,j);
  327.                     i=F.precision;
  328.                 }
  329.                 break;
  330.                 
  331.                 /*  hexadecimal (unsigned)  */
  332.                 
  333.             case 'p': // pointer processing
  334.                 F.havePrecision = F.lSize = TRUE;
  335.                 F.precision = 8;
  336.                 /* ... */
  337.             case 'X':
  338.                 digits = __gCapDigits;
  339.                 goto hexadecimal;
  340.             case 'x':
  341.                 digits =__gLowDigits;
  342.                 /* ... */
  343. hexadecimal:
  344.                 if (F.lSize)
  345.                     n = va_arg(arg, unsigned long);
  346.                 else
  347.                     n = va_arg(arg, unsigned int);
  348.                 if (F.hSize)
  349.                     n = (unsigned short) n;
  350.                 if (!F.havePrecision) {
  351.                     if (F.zeroPad) {
  352.                         F.precision = F.fieldWidth;
  353.                         if (F.altForm)
  354.                             F.precision -= 2;
  355.                     }
  356.                     if (F.precision < 1)
  357.                         F.precision = 1;
  358.                 }
  359.                 for (i = 0; n; n /= 16, i++)
  360.                     *--s = digits[n % 16];
  361.                 if (i<F.precision){
  362.                     j=(F.precision-i);
  363.                     s-=j;
  364.                     BlockMoveData((Ptr)__gZeroString,(Ptr)s,j);
  365.                     i=F.precision;
  366.                 }
  367.                 if (F.altForm) {
  368.                     *--s = c;
  369.                     *--s = '0';
  370.                     i += 2;
  371.                 }
  372.                 break;
  373.                 
  374.  
  375.                 /*  character  */
  376.                 
  377.             case 'c':
  378.                 *--s = va_arg(arg, int);
  379.                 i = 1;
  380.                 break;
  381.                 
  382.                 /*  Error  */
  383.             case 'm':
  384.                 // display the error stored in errno (s_errno);
  385.                 s=buf;
  386.                 i=libsprintf(buf,"%ld",s_errno);
  387.                 break;
  388.                 
  389.                 /*  string  */
  390.                 
  391.             case 's':
  392.                 s = va_arg(arg, char *);
  393.                 i=0;
  394.                 if (F.altForm) {
  395.                     unsigned char* ucp=(unsigned char*)s;
  396.                     unsigned char uc=*ucp;
  397.                     
  398.                     s++;
  399.                     i=(int)0;
  400.                     i+=uc;
  401.                 } else {
  402.                     i = libstrlen(s);
  403.                 }
  404.                 
  405.                 if ((F.havePrecision)&&(i>F.precision))
  406.                     i=F.precision;
  407.                 
  408.                 break;
  409.                 
  410. #ifndef _NOFLOATING_
  411.                 /*  fixed-point  */
  412.  
  413.             case 'f':
  414.                 if (F.LSize)
  415.                     x = va_arg(arg, long double);
  416.                 else
  417.                     x = va_arg(arg, double);
  418.                 if (!F.havePrecision)
  419.                     F.precision = 6;
  420.                 libf2d(1, F.precision, (LibDecRec*)&D, x);
  421.                 D.dot = D.dec.exp + D.dec.sig.length;
  422.                 if ((D.min = D.dot) > 1)
  423.                     D.min = 1;
  424.                 D.max = D.dot + F.precision;
  425.                 if (D.max - D.min > 508)
  426.                     BlockMoveData((Ptr)__gFloatConst,(Ptr)&D.dec.sig, 7);
  427.                 goto floating;
  428.  
  429.                 /*  floating-point  */
  430.                 
  431.             case 'e':
  432.             case 'E':
  433.                 if (F.LSize)
  434.                     x = va_arg(arg, long double);
  435.                 else
  436.                     x = va_arg(arg, double);
  437.                 if (!F.havePrecision)
  438.                     F.precision = 6;
  439.                 F.exponent = c;
  440.                 libf2d(0, D.max = F.precision + 1,  (LibDecRec*)&D, x);
  441.                 D.min = D.dot = 1;
  442.                 D.dec.exp += D.dec.sig.length - 1;
  443.                 goto floating;
  444.                 
  445.                 /*  "general" notation  */
  446.                 
  447.             case 'g':
  448.             case 'G':
  449.                 if (F.LSize)
  450.                     x = va_arg(arg, long double);
  451.                 else
  452.                     x = va_arg(arg, double);
  453.                 if (!F.havePrecision)
  454.                     F.precision = 6;
  455.                 else if (F.precision == 0)
  456.                     F.precision = 1;
  457.                 F.exponent = c - 2;
  458.                 libf2d(0, D.max = F.precision, (LibDecRec*) &D, x);
  459.                 D.min = D.dot = 1;
  460.                 D.dec.exp += D.dec.sig.length - 1;
  461.                 if (D.dec.exp >= -4 && D.dec.exp < F.precision) {
  462.                     F.exponent = 0;
  463.                     if ((D.dot += D.dec.exp) < 1)
  464.                         D.min = D.dot;
  465.                 }
  466.                 if (!F.altForm && D.max > D.dec.sig.length) {
  467.                     if ((D.max = D.dec.sig.length) < D.dot)
  468.                         D.max = D.dot;
  469.                 }
  470.                 goto floating;
  471.                 
  472.                     /*  floating (common code)  */
  473.  
  474. floating:
  475.                 if (D.dec.sig.text[0] > '9') {
  476.                     F.exponent = FALSE;
  477.                     D.dot = 0;
  478.                     D.min = 1;
  479.                     D.max = D.dec.sig.length;
  480.                 }
  481.                 i = 0;
  482.                 if (F.exponent) {
  483.                     n = D.dec.exp < 0 ? -D.dec.exp : D.dec.exp;
  484.                     for (; n; n /= 10, i++)
  485.                         *--s = n % 10 + '0';
  486.                     for (; i < 2; i++)
  487.                         *--s = '0';
  488.                     *--s = D.dec.exp < 0 ? '-' : '+';
  489.                     *--s = F.exponent;
  490.                     i += 2;
  491.                 }
  492.                 j = D.max;
  493.                 if (j == D.dot && !F.altForm)
  494.                     ++D.dot;
  495.                 do {
  496.                     if (j == D.dot) {
  497.                         *--s = '.';
  498.                         i++;
  499.                     }
  500.                     *--s = j > 0 && j <= D.dec.sig.length ? D.dec.sig.text[j-1] : '0';
  501.                 } while (--j >= D.min);
  502.                 i += D.max - j;
  503.                 if (D.dec.sgn)
  504.                     F.sign = '-';
  505.                 else if (F.forceSign)
  506.                     F.sign = '+';
  507.                 if (F.zeroPad) {
  508.                     j = F.fieldWidth;
  509.                     if (F.sign)
  510.                         --j;
  511.                     if (i<j){
  512.                         s -= (j-i);
  513.                         
  514.                         BlockMoveData((Ptr)__gZeroString,(Ptr)s,(j-i));
  515.                         i=j;
  516.                     }
  517.                 }
  518.                 if (F.sign) {
  519.                     *--s = F.sign;
  520.                     i++;
  521.                 }
  522.                 break;
  523. #endif /* _NOFLOATING_ */
  524.                 /*  store # bytes written so far  */
  525.                 
  526.             case 'n':
  527.                 s = (char *)va_arg(arg, void *);
  528.                 if (F.hSize)
  529.                     * (short *) s = nwritten;
  530.                 else if (F.lSize)
  531.                     * (long *) s = nwritten;
  532.                 else
  533.                     * (int *) s = nwritten;
  534.                 continue;
  535.             
  536.                 /*  oops - unknown conversion, abort  */
  537.                 
  538.             default:
  539.                 if (c != '%')
  540.                     goto done;
  541.             copy1:
  542.                 *fp=c;fp++;
  543.                 ++nwritten;
  544.                 continue;
  545.         }
  546.             
  547. EndOfSwitch:
  548.             /*  pad on the left  */
  549.             
  550.         if (i < F.fieldWidth && !F.leftJustify) {
  551.             j=F.fieldWidth-i;
  552.             
  553.             BlockMoveData((Ptr)__gSpaceString,(Ptr)fp,j);
  554.             
  555.             fp+=j;
  556.             nwritten+=j;
  557.             F.fieldWidth=0;
  558.         }
  559.         
  560.             /*  write the converted result  */
  561.         
  562.         BlockMoveData((Ptr)s,(Ptr)fp,i);
  563.         fp+=i;
  564.         nwritten += i;
  565.             
  566.             /*  pad on the right  */
  567.             
  568.         if (i<F.fieldWidth){
  569.             j=F.fieldWidth-i;
  570.             
  571.             BlockMoveData((Ptr)__gSpaceString,(Ptr)fp,j);
  572.             fp+=j;
  573.             nwritten+=j;
  574.         }
  575.     }
  576.     
  577.         /*  all done!  */
  578.         
  579. done:
  580.     *fp=0;
  581.     return nwritten;
  582. }
  583.  
  584. #ifndef _NOFLOATING_
  585.  
  586. static void post_conversion(LibDecRec *d){
  587.     int i;
  588.     /*  strip trailing zeroes  */
  589.  
  590.     for (i = d->dec.sig.length; i > 1 && d->dec.sig.text[i-1] == '0'; --i)
  591.         ++d->dec.exp;
  592.     d->dec.sig.length = i;
  593.         
  594.         /*  format 0, INF, NAN  */
  595.         
  596.     if (d->dec.sig.text[0] == '0') {
  597. /*        d->dec.sgn = 0;             add back to disallow printing "-0"  */
  598.         d->dec.exp = 0;
  599.     }
  600.     else if (d->dec.sig.text[0] == 'I') {
  601.         d->dec.sig.length = 3;
  602.         d->dec.sig.text[1] = 'N';
  603.         d->dec.sig.text[2] = 'F';
  604.     }
  605.     else if (d->dec.sig.text[0] == 'N') {
  606.         d->dec.sig.length = 5;
  607.         d->dec.sig.text[1] = 'A';
  608.         d->dec.sig.text[2] = 'N';
  609.     }
  610. }
  611.  
  612. /* ---------- floating-point conversion ---------- */
  613.  
  614. #if powerc
  615. static void libf2d( int fixed, int precision, LibDecRec *d, long double x){
  616.     struct decform form;
  617.     
  618.     if (precision >= sizeof d->dec.sig)
  619.         precision = sizeof d->dec.sig - 1;
  620.  
  621.     if (fixed)
  622.         form.style = FIXEDDECIMAL;
  623.     else
  624.         form.style = FLOATDECIMAL;
  625.     form.digits = precision;
  626.     /*
  627.         Until the long double data type is really implemented, this must be a call
  628.         to num2dec and not num2decl even though the argument is declared as a long
  629.         double 
  630.     */
  631.     
  632.     num2dec( &form, x, &(d->dec) );
  633.     
  634.         /*  handle fixed-point overflow  */
  635.         
  636.     if (d->dec.sig.text[0] == '?') {
  637.         form.style = FLOATDECIMAL;
  638.         form.digits = sizeof d->dec.sig - 1;
  639.         num2dec( &form, x, &(d->dec));
  640.     }
  641.     post_conversion(d);
  642. #else
  643.  
  644. static void libf2d(int fixed, int precision, LibDecRec *d, long double x){
  645.     struct { char style; short digits; } form;
  646.     REGISTER short *p = (short *) &x;
  647.     
  648.         /*  point to SANE extended  */
  649.  
  650.     #if __option(mc68881) && _NATIVE_FP_
  651.         p[1] = p[0];
  652.     #endif
  653.     #if __option(mc68881) || !_NATIVE_FP_
  654.         p++;
  655.     #endif
  656.     
  657.         /*  convert to decimal record  */
  658.     
  659.     if (precision >= sizeof d->dec.sig)
  660.         precision = sizeof d->dec.sig - 1;
  661.     form.style = fixed;
  662.     form.digits = precision;
  663.     fp68k(&form, p, d, FX2DEC);
  664.     
  665.         /*  handle fixed-point overflow  */
  666.         
  667.     if (d->dec.sig.text[0] == '?') {
  668.         form.style = 0;
  669.         form.digits = sizeof d->dec.sig - 1;
  670.         fp68k(&form, p, d, FX2DEC);
  671.     }
  672.     
  673.     post_conversion(d);    
  674.  
  675. }
  676. #endif // __powerc
  677. #endif // no floating
  678. #endif // use ansi
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.